﻿using System;
using System.Collections.Generic;

namespace XCSerialPort
{
    public class SerialPort_Usb_RegisterManager : ISerialPortManager
    {
        public int currentDeviceIndex = 0; // 当前选择的设备索引
        public bool IsUsbOpen { get; private set; } // 设备打开状态
        private int deviceCount = 0; // 设备数量
        /// <summary>
        /// true为32位寄存器读模式，false为8位寄存器读模式。
        /// </summary>
        public bool isBit32 = false;

        public SerialPort_Usb_RegisterManager() { }

        public SerialPort_Usb_RegisterManager(int _currentDeviceIndex)
        {
            IsUsbOpen = false;
            currentDeviceIndex = _currentDeviceIndex;
        }

        public void SetDeviceConfig(int _currentDeviceIndex)
        {
            currentDeviceIndex = _currentDeviceIndex;
        }

        public void Close(out string msg)
        {
            if (XChipUSB.UsbDestroyUSB())
            {
                IsUsbOpen = false; // 更新状态
                msg = "设备已关闭成功。";
            }
            else
            {
                msg = "关闭设备失败。";
            }
        }

        public string[] GetSerialPorts(out string msg)
        {
            List<string> serialPorts = new List<string>();

            // 初始化 USB 设备
            XChipUSB.UsbIniDevice();
            XChipUSB.UsbUpdateDevice();

            // 获取 USB 设备的数量
            deviceCount = XChipUSB.UsbGetDeviceNum();
            if (deviceCount < 0)
            {
                msg = "获取设备数量失败。";
                return Array.Empty<string>();
            }

            // 获取所有设备信息
            DeviceInfos[] deviceInfoArray = XChipUSB.UsbGetAllDeviceInfoViaMultiplex(deviceCount);

            foreach (var device in deviceInfoArray)
            {
                // 检查 VID 和 PID 是否有效
                if (!string.IsNullOrEmpty(device.VID) && !string.IsNullOrEmpty(device.PID))
                {
                    serialPorts.Add(device.DeviceName); // DeviceName 是串口名称
                }
            }

            msg = $"找到 {serialPorts.Count} 个设备。";
            return serialPorts.ToArray();
        }

        public bool Open(out string msg)
        {
            XChipUSB.UsbIniDevice();
            XChipUSB.UsbUpdateDevice();

            IsUsbOpen = XChipUSB.UsbSelectDevice(currentDeviceIndex);

            if (IsUsbOpen)
            {
                msg = "设备已打开。";
                return true;
            }
            else
            {
                msg = "打开设备失败。";
                return false;
            }
        }


        public bool DeviceStatus()
        {
            return IsUsbOpen;
        }

        public List<ulong> ReadRegister(ulong addr, out string msg, int length = 1, int timeoutMilliseconds = 150)
        {
            List<ulong> values = new List<ulong>();
            msg = ""; // 默认为空，表示无错误

            // 检查设备是否已打开
            if (!IsUsbOpen)
            {
                msg = "设备未打开";
                return null; // 设备未打开，返回 null
            }

            // 循环读取指定数量的数据
            for (int i = 0; i < length; i++)
            {
                uint readValue = 0; // 存储读取到的值
                if (XChipUSB.UsbRegisterRead((uint)(addr + (ulong)i), ref readValue, isBit32)) // 转换为 uint
                {
                    values.Add(readValue); // 存储读取到的值
                }
                else
                {
                    msg = $"地址 0x{addr + (ulong)i:X} 读取失败"; // 更新失败消息
                    return null; // 读取失败，返回 null
                }
            }

            return values; // 返回读取到的所有值
        }

        public void WriteRegister(ulong addr, List<ulong> value, out string msg, int length = 1, int timeoutMilliseconds = 150)
        {
            msg = ""; // 默认为空，表示无错误

            // 检查设备是否已打开
            if (!IsUsbOpen)
            {
                msg = "设备未打开";
                return; // 设备未打开，返回
            }

            // 检查输入值的数量是否与长度一致
            if (value.Count != length)
            {
                msg = "要写入的值数量与指定长度不一致";
                return;
            }

            // 循环写入指定数量的数据
            for (int i = 0; i < length; i++)
            {
                if (!XChipUSB.UsbRegisterWrite((uint)(addr + (ulong)i), (uint)value[i], isBit32)) // 转换为 uint
                {
                    msg = $"地址 0x{addr + (ulong)i:X} 写入失败"; // 更新失败消息
                    return; // 写入失败，返回
                }
            }
        }

        public void SetDeviceConfig(int _Index = 0, uint _deviceID = 0)
        {
            currentDeviceIndex = _Index;
        }
    }
}
